home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-20 | 21.0 KB | 728 lines | [TEXT/PJMM] |
- unit FastBitVector;
-
- {A bit vector (BV) is a fixed-size vector of bits numbered 0..N, where N = size-1.}
- {Bit vector sizes range from 0 to MAXINT. The empty vector (size=0) is supported,}
- {but not particularly useful… Bit vectors are allocated in Mac handles, and are never}
- {locked by this unit; it doesn't buy you anything to lock a bit-vector, so don't bother.}
- {This unit defines operations to manipulate both individual bits and entire bit vectors.}
-
- interface
-
- type
- BitVector = Handle;
- BitVectorSize = 0..MAXINT;
-
- {Call InitFastBitVector once before making any other call.}
- procedure InitFastBitVector;
-
- {NewBV returns nil if it can't allocate a BV of the specified length.}
- {The BV contents are not initialized.}
- function NewBV (length: BitVectorSize): BitVector;
-
- {Call DisposeBV to release the memory occupied by a BV when you}
- {don't need it any more. The BV may not be referenced after DisposeBV.}
- procedure DisposeBV (theBV: BitVector);
-
- {To find out the length of your BV, use this. Remember that indices}
- {run from 0 to length - 1.}
- function BVLength (theBV: BitVector): BitVectorSize;
-
- {The following group of operations changes the new destination size to be the}
- {minimum of the source and original destination sizes. It's OK for the destination}
- {to be the same as a source. The …Cmpl variants complement the bits of src2}
- {before applying the operation.}
- procedure BVCopy (src, dst: BitVector);
- procedure BVBitAND (src1, src2, dst: BitVector);
- procedure BVBitANDCmpl (src1, src2, dst: BitVector);
- procedure BVBitOR (src1, src2, dst: BitVector);
- procedure BVBitORCmpl (src1, src2, dst: BitVector);
- procedure BVBitEOR (src1, src2, dst: BitVector);
- procedure BVBitEORCmpl (src1, src2, dst: BitVector);
- procedure BVBitNOT (src, dst: BitVector);
-
- {BVEqual is true iff the BVs are the same length and same contents.}
- function BVEqual (bv1, bv2: BitVector): Boolean;
-
- {BVUnequal is true iff the BVs are different lengths or have different contents.}
- function BVUnequal (bv1, bv2: BitVector): Boolean;
-
- {These alter the length of a BV. They do nothing if the newLength is not}
- {compatible with the operation, i.e. you can't truncate a BV to make it longer}
- {or extend a BV to make it shorter. BVExpand leaves the additional bits undetermined.}
- {BVAlterLength changes the size either larger or smaller, leaving any new bits undetermined.}
- procedure BVTruncate (bv: BitVector; newLength: BitVectorSize);
- function BVExpand (bv: BitVector; newLength: BitVectorSize): OSErr;
- function BVExtend1 (bv: BitVector; newLength: BitVectorSize): OSErr;
- function BVExtend0 (bv: BitVector; newLength: BitVectorSize): OSErr;
- function BVAlterLength (bv: BitVector; newLength: BitVectorSize): OSErr;
-
- {Set or clear all bits at once.}
- procedure BVSetAllBits (theBV: BitVector);
- procedure BVClearAllBits (theBV: BitVector);
-
- {Test a BV to see whether its bits are all set or all clear.}
- function BVTestAllClear (theBV: BitVector): Boolean;
- function BVTestAllSet (theBV: BitVector): Boolean;
-
- {These set or clear the specified bit if it falls withing the BV.}
- procedure BVSetBit (theBV: BitVector; theBit: Integer);
- procedure BVClearBit (theBV: BitVector; theBit: Integer);
-
- {BVTestBit returns the state of the specified bit if it falls within the BV.}
- function BVTestBit (theBV: BitVector; theBit: Integer): Boolean;
-
- {BVFindNextSetBit scans the BV for the next set bit beyond the specified index,}
- {and updates index to indicate the found bit. When no more bits, index becomes -1.}
- {To find all set bits, start with index = -1 and call until index becomes -1 again.}
- procedure BVFindNextSetBit (bv: BitVector; var index: Integer);
-
- {BVMoveBits copies a run of bits from the src BV into the dst BV at a specified position.}
- {The dst BV is never extended - moved bits are lost if they won't fit into the dst BV.}
- procedure BVMoveBits (src: BitVector; start, length: Integer; dst: BitVector; position: Integer);
-
- {BVCatenate extends the first BV with the bits from the second BV.}
- function BVCatenate (bv1, bv2: BitVector): OSErr;
-
- {BVLoadBits and BVStoreBits move _only_ the bits (not the size) of a bit-vector to}
- {a specified location in memory. You have to be sure the in-memory structure}
- {matches the size of the bit vector data. Note that you have to leave space for the}
- {entire last byte of the data, even if not all bits are used.}
- procedure BVLoadBits (theBV: BitVector; theBits: Ptr);
- procedure BVStoreBits (theBV: BitVector; theBits: Ptr);
-
- {The M variants work on data stored at a fixed location in memory. None of these}
- {can modify the size of the bit vector. No range checking is done. For some routines,}
- {an extra parameter is added to specify the length of the vector in bits.}
- procedure BVMClearAllBits (theBits: Ptr; length: BitVectorSize);
- function BVMEqual (theBits1, theBits2: Ptr; length: BitVectorSize): Boolean;
- procedure BVMSetBit (theBits: Ptr; theBit: Integer);
- procedure BVMClearBit (theBits: Ptr; theBit: Integer);
- function BVMTestBit (theBits: Ptr; theBit: Integer): Boolean;
-
- implementation
-
- {NOTE: All inline code is documented in Fast-bv.lap.lisp.}
-
- {The general strategy is to perform all operations bytewise (yes, slightly suboptimal in terms of speed,}
- {but smaller code) using inline routines, and fix up the boundary bytes with special-case code if needed.}
- {We always make sure that any unused bits in the last byte are set to zero.}
-
- type
- LookupTables = packed record
- masks: packed array[0..7] of SignedByte;
- offsets: packed array[0..255] of SignedByte;
- end;
- LookupTablesPtr = ^LookupTables;
- LookupTablesHandle = ^LookupTablesPtr;
-
- var
- BVLookups: LookupTablesHandle;
-
- procedure InitFastBitVector;
- var
- i, v: Integer;
- begin
- BVLookups := LookupTablesHandle(NewHandleClear(SIZEOF(LookupTables)));
- with BVLookups^^ do
- begin
- v := $FF;
- for i := 0 to 7 do
- begin
- masks[i] := v;
- v := BSR(v, 1);
- end;
- offsets[1] := -1;
- offsets[2] := -2;
- offsets[4] := -3;
- offsets[8] := -4;
- offsets[16] := -5;
- offsets[32] := -6;
- offsets[64] := -7;
- offsets[128] := -8;
- for i := 1 to 255 do
- begin
- if offsets[i] <> 0 then
- v := offsets[i]
- else
- offsets[i] := v;
- end;
- end;
- end;
-
- type
- BVRec = record
- len: BitVectorSize;
- case Integer of
- 0: (
- vec: packed array[1..1] of Boolean;
- );
- 1: (
- bytes: packed array[1..1] of SignedByte;
- );
- end;
- BVPtr = ^BVRec;
- BVHdl = ^BVPtr;
-
- function NewBV (length: BitVectorSize): BitVector;
- var
- bvH: BVHdl;
- begin
- bvH := BVHdl(NewHandle(SIZEOF(BitVectorSize) + (length + 7) div 8));
- bvH^^.len := length;
- NewBV := BitVector(bvH);
- end;
-
- procedure DisposeBV (theBV: BitVector);
- begin
- DisposHandle(Handle(theBV));
- end;
-
- function BVLength (theBV: BitVector): BitVectorSize;
- begin
- BVLength := BVHdl(theBV)^^.len;
- end;
-
- function VecBytes (bv: BVHdl): Integer;
- begin
- VecBytes := (bv^^.len + 7) div 8
- end;
-
- procedure ClearEndFill (bv: BVHdl);
- var
- lastByte, residue: Integer;
- begin
- lastByte := VecBytes(bv);
- residue := bv^^.len mod 8;
- if residue > 0 then
- with bv^^ do
- bytes[lastByte] := BAND(bytes[lastByte], BNOT(BVLookups^^.masks[residue]));
- end;
-
- procedure ConformLength (src1, src2, dst: BVHdl);
- var
- minLen: BitVectorSize;
- begin
- minLen := src1^^.len;
- with src2^^ do
- if len < minLen then
- minLen := len;
- with dst^^ do
- begin
- if len < minLen then
- minLen := len;
- if minLen < len then
- begin
- len := minLen;
- SetHandleSize(Handle(dst), SIZEOF(BitVectorSize) + VecBytes(dst));
- ClearEndFill(dst);
- end;
- end;
- end;
-
- procedure BVCopy (src, dst: BitVector);
- var
- bvSH, bvDH: BVHdl;
- begin
- bvSH := BVHdl(src);
- bvDH := BVHdl(dst);
- ConformLength(bvSH, bvSH, bvDH);
- BlockMove(@bvSH^^.vec, @bvDH^^.vec, VecBytes(bvDH));
- end;
-
- procedure BlockFill_Inline (value: SignedByte; block: Ptr; length: Integer);
- inline
- $321F, $5341, $205F, $301F, $10C0, $51C9, $FFFC;
-
- procedure BVSetAllBits (theBV: BitVector);
- var
- bvH: BVHdl;
- begin
- bvH := BVHdl(theBV);
- BlockFill_Inline($FF, @bvH^^.vec, VecBytes(bvH));
- ClearEndFill(bvH);
- end;
-
- function BitIndexOK (theBV: BitVector; theBit: Integer): Boolean;
- begin
- BitIndexOK := (theBit >= 0) and (theBit < BVHdl(theBV)^^.len);
- end;
-
- procedure BVSetBit (theBV: BitVector; theBit: Integer);
- var
- bvH: BVHdl;
- begin
- bvH := BVHdl(theBV);
- if BitIndexOK(theBV, theBit) then
- BitSet(@bvH^^.vec, theBit);
- end;
-
- procedure BVClearAllBits (theBV: BitVector);
- var
- bvH: BVHdl;
- begin
- bvH := BVHdl(theBV);
- BlockFill_Inline($00, @bvH^^.vec, VecBytes(bvH));
- end;
-
- procedure BVClearBit (theBV: BitVector; theBit: Integer);
- var
- bvH: BVHdl;
- begin
- bvH := BVHdl(theBV);
- if BitIndexOK(theBV, theBit) then
- BitClr(@bvH^^.vec, theBit);
- end;
-
- function BVTestBit (theBV: BitVector; theBit: Integer): Boolean;
- var
- bvH: BVHdl;
- begin
- bvH := BVHdl(theBV);
- BVTestBit := BitTst(@bvH^^.vec, theBit);
- end;
-
- function BlockAllClear_Inline (bv: Ptr; length: Integer): Boolean;
- inline
- $321F, $5341, $205F, $4A18, $56C9, $FFFC, $57EF, $0001, {}
- $442F, $0001;
-
- function BVTestAllClear (theBV: BitVector): Boolean;
- var
- bvH: BVHdl;
- len, byteCount: Integer;
- allZero: Boolean;
- begin
- bvH := BVHdl(theBV);
- len := bvH^^.len;
- byteCount := VecBytes(bvH);
- {$PUSH}
- {$R-}
- allZero := BAND(bvH^^.bytes[byteCount], BNOT(BVLookups^^.masks[len mod 8])) = 0;
- {$POP}
- if allZero & (byteCount > 1) then
- allZero := BlockAllClear_Inline(@bvH^^.vec, byteCount - 1);
- BVTestAllClear := allZero;
- end;
-
- function BlockAllSet_Inline (bv: Ptr; length: Integer): Boolean;
- inline
- $321F, $5341, $205F, $4A18, $57C9, $FFFC, $56EF, $0001, {}
- $442F, $0001;
-
- function BVTestAllSet (theBV: BitVector): Boolean;
- var
- bvH: BVHdl;
- len, byteCount: Integer;
- allOnes: Boolean;
- begin
- bvH := BVHdl(theBV);
- len := bvH^^.len;
- byteCount := VecBytes(bvH);
- {$PUSH}
- {$R-}
- allOnes := BOR(bvH^^.bytes[byteCount], BVLookups^^.masks[len mod 8]) = $FF;
- {$POP}
- if allOnes & (byteCount > 1) then
- allOnes := BlockAllSet_Inline(@bvH^^.vec, byteCount - 1);
- BVTestAllSet := allOnes;
- end;
-
- function BlockEqual_Inline (bv1, bv2: Ptr; length: Integer): Boolean;
- inline
- $321F, $5341, $225F, $205F, $B308, $56C9, $FFFC, $57EF, {}
- $0001, $442F, $0001;
-
- function BVEqual (bv1, bv2: BitVector): Boolean;
- var
- bv1H, bv2H: BVHdl;
- len: Integer;
- begin
- bv1H := BVHdl(bv1);
- bv2H := bvHdl(bv2);
- len := bv1H^^.len;
- if len <> bv2H^^.len then
- BVEqual := False
- else
- BVEqual := BlockEqual_Inline(@bv1H^^.vec, @bv2H^^.vec, VecBytes(bv1H));
- end;
-
- function BlockUnequal_Inline (bv1, bv2: Ptr; length: Integer): Boolean;
- inline
- $321F, $5341, $225F, $205F, $B308, $57C9, $FFFC, $56EF, {}
- $0001, $442F, $0001;
-
- function BVUnequal (bv1, bv2: BitVector): Boolean;
- var
- bv1H, bv2H: BVHdl;
- len: Integer;
- begin
- bv1H := BVHdl(bv1);
- bv2H := bvHdl(bv2);
- len := bv1H^^.len;
- if len <> bv2H^^.len then
- BVUnequal := True
- else
- BVUnequal := BlockUnequal_Inline(@bv1H^^.vec, @bv2H^^.vec, VecBytes(bv1H));
- end;
-
- procedure BlockAND_Inline (src1, src2, dst: Ptr; length: Integer);
- inline
- $2F0A, $321F, $5341, $245F, $225F, $205F, $1018, $C019, {}
- $14C0, $51C9, $FFF8, $245F;
-
- procedure BVBitAND (src1, src2, dst: BitVector);
- var
- bv1H, bv2H, bvDH: BVHdl;
- begin
- bv1H := BVHdl(src1);
- bv2H := BVHdl(src2);
- bvDH := BVHdl(dst);
- ConformLength(bv1H, bv2H, bvDH);
- BlockAND_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
- end;
-
- procedure BlockANDCmpl_Inline (src1, src2, dst: Ptr; length: Integer);
- inline
- $2F0A, $321F, $5341, $245F, $225F, $205F, $1019, $4600, {}
- $C018, $14C0, $51C9, $FFF6, $245F;
-
- procedure BVBitANDCmpl (src1, src2, dst: BitVector);
- var
- bv1H, bv2H, bvDH: BVHdl;
- begin
- bv1H := BVHdl(src1);
- bv2H := BVHdl(src2);
- bvDH := BVHdl(dst);
- ConformLength(bv1H, bv2H, bvDH);
- BlockANDCmpl_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
- end;
-
- procedure BlockOR_Inline (src1, src2, dst: Ptr; length: Integer);
- inline
- $2F0A, $321F, $5341, $245F, $225F, $205F, $1018, $8019, {}
- $14C0, $51C9, $FFF8, $245F;
-
- procedure BVBitOR (src1, src2, dst: BitVector);
- var
- bv1H, bv2H, bvDH: BVHdl;
- begin
- bv1H := BVHdl(src1);
- bv2H := BVHdl(src2);
- bvDH := BVHdl(dst);
- ConformLength(bv1H, bv2H, bvDH);
- BlockOR_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
- end;
-
- procedure BlockORCmpl_Inline (src1, src2, dst: Ptr; length: Integer);
- inline
- $2F0A, $321F, $5341, $245F, $225F, $205F, $1019, $4600, {}
- $8018, $14C0, $51C9, $FFF6, $245F;
-
- procedure BVBitORCmpl (src1, src2, dst: BitVector);
- var
- bv1H, bv2H, bvDH: BVHdl;
- begin
- bv1H := BVHdl(src1);
- bv2H := BVHdl(src2);
- bvDH := BVHdl(dst);
- ConformLength(bv1H, bv2H, bvDH);
- BlockORCmpl_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
- ClearEndFill(bvDH);
- end;
-
- procedure BlockEOR_Inline (src1, src2, dst: Ptr; length: Integer);
- inline
- $2F0A, $321F, $5341, $245F, $225F, $205F, $1018, $1219, {}
- $B300, $14C0, $51C9, $FFF6, $245F;
-
- procedure BVBitEOR (src1, src2, dst: BitVector);
- var
- bv1H, bv2H, bvDH: BVHdl;
- begin
- bv1H := BVHdl(src1);
- bv2H := BVHdl(src2);
- bvDH := BVHdl(dst);
- ConformLength(bv1H, bv2H, bvDH);
- BlockEOR_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
- end;
-
- procedure BlockEORCmpl_Inline (src1, src2, dst: Ptr; length: Integer);
- inline
- $2F0A, $321F, $5341, $245F, $225F, $205F, $1219, $4601, {}
- $1018, $B300, $14C0, $51C9, $FFF4, $245F;
-
- procedure BVBitEORCmpl (src1, src2, dst: BitVector);
- var
- bv1H, bv2H, bvDH: BVHdl;
- begin
- bv1H := BVHdl(src1);
- bv2H := BVHdl(src2);
- bvDH := BVHdl(dst);
- ConformLength(bv1H, bv2H, bvDH);
- BlockEORCmpl_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
- ClearEndFill(bvDH);
- end;
-
- procedure BlockNOT_Inline (src, dst: Ptr; length: Integer);
- inline
- $321F, $5341, $225F, $205F, $1018, $4600, $12C0, $51C9, {}
- $FFF8;
-
- procedure BVBitNOT (src, dst: BitVector);
- var
- bvSH, bvDH: BVHdl;
- begin
- bvSH := BVHdl(src);
- bvDH := BVHdl(dst);
- ConformLength(bvSH, bvSH, bvDH);
- BlockNOT_Inline(@bvSH^^.vec, @bvDH^^.vec, VecBytes(bvDH));
- ClearEndFill(bvDH);
- end;
-
- procedure BVTruncate (bv: BitVector; newLength: BitVectorSize);
- var
- bvH: BVHdl;
- begin
- bvH := BVHdl(bv);
- with bvH^^ do
- if newLength < len then
- begin
- len := newLength;
- SetHandleSize(Handle(bvH), SIZEOF(BitVectorSize) + VecBytes(bvH));
- ClearEndFill(bvH);
- end;
- end;
-
- function BVExpand (bv: BitVector; newLength: BitVectorSize): OSErr;
- var
- bvH: BVHdl;
- err: OSErr;
- begin
- bvH := BVHdl(bv);
- if newLength > bvH^^.len then
- bvH^^.len := newLength;
- SetHandleSize(Handle(bvH), SIZEOF(BitVectorSize) + VecBytes(bvH));
- err := MemError;
- BVExpand := err;
- if err = noErr then
- ClearEndFill(bvH);
- end;
-
- function BVAlterLength (bv: BitVector; newLength: BitVectorSize): OSErr;
- var
- bvH: BVHdl;
- err: OSErr;
- begin
- bvH := BVHdl(bv);
- SetHandleSize(Handle(bvH), SIZEOF(BitVectorSize) + VecBytes(bvH));
- err := MemError;
- BVAlterLength := err;
- end;
-
- function BVExtend1 (bv: BitVector; newLength: BitVectorSize): OSErr;
- var
- bvH: BVHdl;
- oldLen: BitVectorSize;
- oldByteCount, oldResidue, extraByteCount: Integer;
- err: OSErr;
- begin
- bvH := BVHdl(bv);
- oldLen := bvH^^.len;
- oldByteCount := VecBytes(bvH);
- err := BVExpand(bv, newLength);
- BVExtend1 := err;
- if err = noErr then
- begin
- oldResidue := oldLen mod 8;
- if oldResidue > 0 then
- with bvH^^ do
- {$PUSH}
- {$R-}
- bytes[oldByteCount] := BOR(bytes[oldByteCount], BVLookups^^.masks[oldResidue]);
- {$POP}
- extraByteCount := VecBytes(bvH) - oldByteCount;
- if extraByteCount > 0 then
- begin
- {$PUSH}
- {$R-}
- BlockFill_Inline($FF, @bvH^^.bytes[oldByteCount + 1], extraByteCount);
- {$POP}
- ClearEndFill(bvH);
- end;
- end;
- end;
-
- function BVExtend0 (bv: BitVector; newLength: BitVectorSize): OSErr;
- var
- bvH: BVHdl;
- oldLen: BitVectorSize;
- oldByteCount, oldResidue, extraByteCount: Integer;
- err: OSErr;
- begin
- bvH := BVHdl(bv);
- oldLen := bvH^^.len;
- oldByteCount := VecBytes(bvH);
- err := BVExpand(bv, newLength);
- BVExtend0 := err;
- if err = noErr then
- begin
- oldResidue := oldLen mod 8;
- if oldResidue > 0 then
- with bvH^^ do
- {$PUSH}
- {$R-}
- bytes[oldByteCount] := BAND(bytes[oldByteCount], BNOT(BVLookups^^.masks[oldResidue]));
- {$POP}
- extraByteCount := VecBytes(bvH) - oldByteCount;
- if extraByteCount > 0 then
- {$PUSH}
- {$R-}
- BlockFill_Inline($00, @bvH^^.bytes[oldByteCount + 1], extraByteCount);
- {$POP}
- end;
- end;
-
- procedure NextBit_Inline (table: Ptr; bvPtr: Ptr; var index: Integer);
- inline {Optimized for relatively sparse bit-vectors}
- $48E7, $1020, $225F, $3011, $205F, $245F, $2F09, $3418, {}
- $2248, $5240, $B042, $6C36, $3600, $E648, $48C0, $D1C0, {}
- $5E42, $E64A, $9440, $5342, $4241, $1218, $C67C, $0007, {}
- $C232, $30F8, $6002, $1218, $56CA, $FFFC, $6710, $1232, {}
- $1000, $4881, $91C9, $3008, $E748, $D240, $6004, $323C, {}
- $FFFF, $225F, $3281, $4CDF, $0408;
-
- procedure BVFindNextSetBit (bv: BitVector; var index: Integer);
- begin
- NextBit_Inline(@BVLookups^^.offsets, Ptr(bv^), index);
- end;
-
- procedure BlockShiftBitsLeft_Inline (src, dst: Ptr; shift, length: Integer);
- inline {Shift source data left by 1..7 bits while copying to destination.}
- $48E7, $1800, $381F, $5344, $341F, $3602, $4443, $5043, {}
- $225F, $205F, $4240, $1018, $E528, $1210, $E629, $8001, {}
- $12C0, $51CC, $FFF0, $4CDF, $0018;
-
- procedure BVMoveBits (src: BitVector; start, length: Integer; dst: BitVector; position: Integer);
- var
- bvS, bvD: BVHdl;
- startResidue, positionResidue: Integer;
- srcLength, dstLength: Integer;
- srcBytesBegin, dstBytesBegin, bytesToCopy, shiftCount, mask, lastDstByte: Integer;
- aByte: SignedByte;
- begin
- {• This is unfinished - The general form is OK, but lots of “fenceposts” need adjusting…}
- bvS := BVHdl(src);
- bvD := BVHdl(dst);
- srcLength := bvS^^.len;
- dstLength := bvD^^.len;
- if (start < srcLength) and (position < dstLength) then
- begin
- if start + length > srcLength then
- length := srcLength - start;
- if position + length > dstLength then
- length := dstLength - position;
- bytesToCopy := length div 8;
- srcBytesBegin := start div 8;
- startResidue := start mod 8;
- if startResidue > 0 then
- begin
- srcBytesBegin := srcBytesBegin + 1;
- bytesToCopy := bytesToCopy - 1;
- end;
- dstBytesBegin := position div 8;
- lastDstByte := dstBytesBegin + bytesToCopy;
- positionResidue := position mod 8;
- if positionResidue > 0 then
- dstBytesBegin := dstBytesBegin + 1;
- if startResidue = positionResidue then
- begin
- mask := BVLookups^^.masks[positionResidue];
- {$PUSH}
- {$R-}
- bvD^^.bytes[dstBytesBegin] := BOR(BAND(bvS^^.bytes[srcBytesBegin], mask), BAND(bvD^^.bytes[srcBytesBegin], BNOT(mask)));
- BlockMove(@bvS^^.bytes[srcBytesBegin], @bvD^^.bytes[dstBytesBegin], bytesToCopy);
- {$POP}
- mask := BVLookups^^.masks[(position + length) mod 8];
- {$PUSH}
- {$R-}
- bvD^^.bytes[lastDstByte] := BOR(BAND(bvS^^.bytes[srcBytesBegin + bytesToCopy], mask), BAND(bvD^^.bytes[lastDstByte], BNOT(mask)));
- {$POP}
- end
- else
- begin
- shiftCount := positionResidue - startResidue;
- if shiftCount < 0 then
- begin
- shiftCount := shiftCount + 8;
- end;
- {$PUSH}
- {$R-}
- BlockShiftBitsLeft_Inline(@bvS^^.bytes[srcBytesBegin], @aByte, shiftCount, 1);
- {$POP}
- mask := BVLookups^^.masks[shiftCount];
- bvD^^.bytes[dstBytesBegin] := BOR(BAND(aByte, mask), BAND(bvD^^.bytes[srcBytesBegin], BNOT(mask)));
- {$PUSH}
- {$R-}
- BlockShiftBitsLeft_Inline(@bvS^^.bytes[srcBytesBegin], @bvD^^.bytes[dstBytesBegin], shiftCount, bytesToCopy);
- {$POP}
- mask := BVLookups^^.masks[(position + length) mod 8];
- {$PUSH}
- {$R-}
- BlockShiftBitsLeft_Inline(@bvS^^.bytes[srcBytesBegin + bytesToCopy], @aByte, shiftCount, 1);
- bvD^^.bytes[lastDstByte] := BOR(BAND(aByte, mask), BAND(bvD^^.bytes[lastDstByte], BNOT(mask)));
- {$POP}
- end;
- end;
- end;
-
- function BVCatenate (bv1, bv2: BitVector): OSErr;
- var
- bv1Length, bv2Length: Integer;
- err: OSErr;
- begin
- bv1Length := BVLength(bv1);
- bv2Length := BVLength(bv2);
- err := BVExpand(bv1, bv1Length + bv2Length);
- BVCatenate := err;
- if err = noErr then
- BVMoveBits(bv2, 0, bv2Length, bv1, bv1Length);
- end;
-
- procedure BVLoadBits (theBV: BitVector; theBits: Ptr);
- begin
- with BVHdl(theBV)^^ do
- BlockMove(theBits, @bytes, VecBytes(BVHdl(theBV)));
- end;
-
- procedure BVStoreBits (theBV: BitVector; theBits: Ptr);
- begin
- with BVHdl(theBV)^^ do
- BlockMove(@bytes, theBits, VecBytes(BVHdl(theBV)));
- end;
-
- procedure BVMClearAllBits (theBits: Ptr; length: BitVectorSize);
- begin
- BlockFill_Inline($00, theBits, (length + 7) div 8);
- end;
-
- function BVMEqual (theBits1, theBits2: Ptr; length: BitVectorSize): Boolean;
- begin
- BVMEqual := BlockEqual_Inline(theBits1, theBits2, (length + 7) div 8);
- end;
-
- procedure BVMSetBit (theBits: Ptr; theBit: Integer);
- begin
- BitSet(theBits, theBit);
- end;
-
- procedure BVMClearBit (theBits: Ptr; theBit: Integer);
- begin
- BitClr(theBits, theBit);
- end;
-
- function BVMTestBit (theBits: Ptr; theBit: Integer): Boolean;
- begin
- BVMTestBit := BitTst(theBits, theBit);
- end;
-
- end.